package com.ygqh.baby.service.wechat;

import com.foxinmy.weixin4j.api.Pay3Api;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.mch.*;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.type.SignType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.exception.YgException;
import com.ygqh.baby.po.YgOrderPayLog;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.wechat.api.YgPay3Api;
import com.ygqh.baby.service.wechat.notify.PayNotifyData;
import com.ygqh.baby.service.wechat.notify.PayNotifyTemplate;
import com.ygqh.baby.service.wechat.notify.PaySuccessCallBack;
import com.ygqh.baby.service.wechat.protocol.UnifiedOrderReqData;
import com.ygqh.baby.service.wechat.protocol.UnifiedOrderResData;
import com.ygqh.baby.service.wechat.util.XMLParser;
import com.ygqh.baby.utils.ExceptionUtil;
import com.ygqh.baby.utils.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.xml.sax.SAXException;

import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
public class YgWeChatServiceImpl implements YgWeChatService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private YgOrderService orderService;
    @Autowired
    private YgOrderPaymentService ygOrderPaymentService;
    @Autowired
    private YgOrderLogService ygOrderLogService;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private KsdOrderService ksdOrderService;
    @Autowired
    private YgRechargeMemberRecordService ygRechargeMemberRecordService;
    @Autowired
    private YgOrderPayLogService ygOrderPayLogService;
    @Autowired
    private FileService fileService;
    @Value("${micro.msg.appId}")
    private String appid;
    @Value("${wechat.pay.mchid}")
    private String mchid;
    @Value("${micro.msg.secret}")
    private String appsecret;
    @Value("${wechat.pay.key}")
    private String key;

    @Override
    public Message UnifiedOrderJSAPI(UnifiedOrderReqData reqData) {
        String postDataXML = null;
        String res = null;
        UnifiedOrderResData resData;
        try {
            postDataXML = XMLParser.toXML(reqData);
            ygOrderLogService.addOrderLog(Long.parseLong(reqData.getOut_trade_no()), OrderStatus.WaitingPay, "JSAPI", postDataXML);
            res = HttpUtil.con_post(PayURLConsts.MCH_UNIFIEDORDER_URL, postDataXML);
            logger.debug("UnifiedOrder get response:" + res);
            resData = XMLParser.getObjectFromXML(res, UnifiedOrderResData.class);
            if ("SUCCESS".equals(resData.getReturn_code()) && "SUCCESS".equals(resData.getResult_code())) {
                PayRequest payRequest = new PayRequest(resData.getAppid(), "prepay_id=" + resData.getPrepay_id());
                payRequest.setSignType(SignType.MD5);
                payRequest.setPaySign(DigestUtil.paysignMd5(payRequest, key));
                logger.debug("UnifiedOrder get bridge:" + payRequest);
                payRequest.setPrepayId(resData.getPrepay_id());

                return Message.success("微信jsapi支付，统一下单成功", payRequest);
            }
            logger.warn("微信jsapi支付，统一下单失败；" + resData.getReturn_msg() + "paymentCode" + reqData.getOut_trade_no());

        } catch (Exception e) {

            logger.error("微信统一下单失败，{}", e.getMessage());
        } finally {
            try {
                List<YgOrderPayLog> logs = new ArrayList<>();
                YgOrderPayLog request = new YgOrderPayLog(reqData.getOut_trade_no(), null, PayType.WeChat.name(), "Resquest",
                        postDataXML == null ? "支付异常" : postDataXML, DataStatus.Valid.name());
                YgOrderPayLog responseMsg = new YgOrderPayLog(reqData.getOut_trade_no(), null, PayType.WeChat.name(), "Response",
                        res == null ? "支付异常" : res, DataStatus.Valid.name());
                logs.add(request);
                logs.add(responseMsg);
                //添加支付请求记录
                ygOrderPayLogService.addPayLog(logs);
            } catch (Exception ignored) {

            }

        }
        return Message.error("微信jsapi支付，统一下单失败；", reqData.getOut_trade_no());

    }

    @Override
    public String UnifiedOrderCallBack(String requestXml) {
        return new PayNotifyTemplate(requestXml).execute(payNotifyData -> new Thread(() -> {
            PayType payType = PayType.WeChat;
            AppType appType = AppType.WeChat;
            ygOrderPayLogService.addPayLog(payNotifyData.getOut_trade_no(), null, payType, "Notify", requestXml);
            String payAppid = payNotifyData.getAppid();
            String subAppId = payNotifyData.getSub_appid();
            if (!payAppid.equals(appid) || StringUtil.isNotBlank(subAppId)) {
                appType = AppType.Small;
            }

            String paymentCode = payNotifyData.getOut_trade_no();
            String transactionId = payNotifyData.getTransaction_id();
            int totalFee = Integer.parseInt(payNotifyData.getTotal_fee());
            BigDecimal totalPrice = new BigDecimal(totalFee).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_DOWN);
            ygOrderLogService.addOrderLog(Long.parseLong(paymentCode), OrderStatus.WaitingPay, "系统,微信支付回调",
                    "接收到微信支付回调，这里的orderId是支付流水号。transactionId=" + transactionId);
            // 订单支付成功处理业务逻辑
            orderService.doBussness4PaySuccess(paymentCode, transactionId, totalPrice, appType, payType);


        }).start());
    }

    @Override
    public Message UnifiedOrderNATIVE(UnifiedOrderReqData reqData) throws IOException, SAXException, ParserConfigurationException, IllegalAccessException {
        // String res = HttpService.doPost(Configure.UNIFIED_ORDER_API,
        // reqData);
        String postDataXML = XMLParser.toXML(reqData);
        ygOrderLogService.addOrderLog(Long.parseLong(reqData.getOut_trade_no()), OrderStatus.WaitingPay, "NATIVE", postDataXML);
        String res = HttpUtil.con_post(PayURLConsts.MCH_UNIFIEDORDER_URL, postDataXML);
        logger.debug("UnifiedOrder get response:" + res);
        UnifiedOrderResData resData = XMLParser.getObjectFromXML(res, UnifiedOrderResData.class);

        if ("SUCCESS".equals(resData.getReturn_code()) && "SUCCESS".equals(resData.getResult_code())) {

            logger.debug("UnifiedOrder get bridge:" + resData.toString());
            System.out.println(resData.toString());

            return Message.success("微信扫码支付（模式二），统一下单成功", resData.getCode_url());
        }
        logger.warn("微信扫码支付（模式二），统一下单失败；" + resData.getReturn_msg() + "paymentCode" + reqData.getOut_trade_no());
        return Message.error("微信扫码支付（模式二），统一下单失败", reqData.getOut_trade_no());
    }

    /**
     * 充值会员（代理）取消卡券和宝宝生日的设置
     * <p>
     * 2018-05-14
     */
    @Override
    public String rechargeCallBack(String result) {
        return new PayNotifyTemplate(result).execute(payNotifyData -> new Thread(() -> {
            try {
                // 插入充值记录
                Long paymentCode = Long.parseLong(payNotifyData.getOut_trade_no());
                int total_fee = Integer.parseInt(payNotifyData.getTotal_fee());
                BigDecimal paidPrice = new BigDecimal(total_fee).divide(new BigDecimal(100));
                String[] split = payNotifyData.getAttach().split("-");
                Long userId = Long.parseLong(split[0]);
                String rechargeType = split[1];

                String transactionId = payNotifyData.getTransaction_id();
                // 处理业务、
                if (rechargeType.endsWith(CodeType.RechargeMB.name())
                        || rechargeType.endsWith(CodeType.RechargeAG.name())) {
                    /*String cardIds = split[2];
                    Date birthday = new Date(Long.parseLong(split[3]));
                    ygRechargeMemberRecordService.doPaySuccessBusiness(paymentCode, paidPrice, userId, transactionId, cardIds, birthday);*/
                    ygRechargeMemberRecordService.doPaySuccessBusiness(paymentCode, paidPrice, userId, transactionId);
                }
                // 回写用户的openID
                YgUser ygUser = ygUserService.findById(userId);
                if (StringUtil.isBlank(ygUser.getOpenId())) {
                    ygUserService.bindingOpenId(userId, payNotifyData.getOpenid(), null, null);
                }

            } catch (Exception e) {
                e.printStackTrace();
                logger.error("微信回调处理业务报错" + ExceptionUtil.getExceptionMsg(e));
            }
        }).start());
    }

    @Override
    public RefundResult refund(String returnCode, BigDecimal refundPrice, BigDecimal orderPrice, String orderPayCode) throws YgException {
        RefundResult result = null;
        try {
            InputStream inputStream = fileService.downloadIOFromOss("cert/apiclient_cert.p12");

            WeixinPayAccount weixinAccount = new WeixinPayAccount(appid, appsecret, key, mchid);
            Pay3Api pay3Api = new Pay3Api(weixinAccount);
            IdQuery idQuery = new IdQuery(orderPayCode, IdType.TRADENO);
            result = pay3Api.refundApply(inputStream, idQuery, returnCode, orderPrice.doubleValue(), refundPrice.doubleValue(), CurrencyType.CNY, mchid);

        } catch (Exception e) {
            YgException exception = null;
            e.printStackTrace();
            if (e instanceof WeixinException) {
                exception = new YgException(((WeixinException) e).getErrorCode(), ((WeixinException) e).getErrorMsg());
                System.out.println(exception.getMessage());
            } else if (e instanceof IOException) {
                exception = new YgException("读取证书失败", e.toString());
            } else {
                exception = new YgException(e.getMessage());
            }
            throw exception;
        }
        return result;
    }

    @Override
    public RefundRecord refundQuery(String returnOrderCode) throws YgException {
        RefundRecord refundQuery = null;
        WeixinPayAccount weixinAccount = new WeixinPayAccount(appid, appsecret, key, mchid);
        Pay3Api pay3Api = new Pay3Api(weixinAccount);
        IdQuery idQuery = new IdQuery(returnOrderCode, IdType.REFUNDNO);
        try {
            refundQuery = pay3Api.refundQuery(idQuery);
        } catch (WeixinException e) {
            e.printStackTrace();
            YgException exception = new YgException(((WeixinException) e).getErrorCode(), ((WeixinException) e).getErrorMsg());
            System.out.println(exception.getMessage());
            throw exception;
        }

        return refundQuery;
    }

    @Override
    public String KSDUnifiedOrderCallBack(String requestXml) {
        String responseXml = new PayNotifyTemplate(requestXml).execute(new PaySuccessCallBack() {
            @Override
            public void onSuccess(PayNotifyData payNotifyData) {
                new Thread(() -> {
                    String paymentCode = payNotifyData.getOut_trade_no();
                    String transactionId = payNotifyData.getTransaction_id();
                    int total_fee = Integer.parseInt(payNotifyData.getTotal_fee());
                    BigDecimal totalPrice = new BigDecimal(total_fee).divide(new BigDecimal(100));
                    String openId = payNotifyData.getOpenid();
                    ygOrderLogService.addOrderLog(Long.parseLong(paymentCode), OrderStatus.WaitingPay, "系统,微信支付回调",
                            "接收到微信支付回调，这里的orderId是支付流水号。transactionId=" + transactionId);
                    // 订单支付成功处理业务逻辑
                    ksdOrderService.paySuccess(paymentCode, transactionId, openId, totalPrice);
                }).start();
            }
        });
        return responseXml;
    }

    @Override
    public RedpacketSendResult sendRedpack(Redpacket redpacket) throws YgException {
        try {
            WeixinPayAccount weixinAccount = new WeixinPayAccount(appid, appsecret, key, mchid);
            YgPay3Api api = new YgPay3Api(weixinAccount);
            InputStream inputStream = fileService.downloadIOFromOss("cert/apiclient_cert.p12");
            return api.sendredpack(redpacket, inputStream);
        } catch (Exception e) {
            YgException exception = null;
            e.printStackTrace();
            if (e instanceof WeixinException) {
                exception = new YgException(((WeixinException) e).getErrorCode(), ((WeixinException) e).getErrorMsg());
                System.out.println(exception.getMessage());
            } else if (e instanceof IOException) {
                exception = new YgException("读取证书失败", e.toString());
            } else {
                exception = new YgException(e.getMessage());
            }
            throw exception;
        }
    }

    @Override
    public RedpacketRecord queryRedpack(String outTradeNo) throws WeixinException {
        WeixinPayAccount weixinAccount = new WeixinPayAccount(appid, appsecret, key, mchid);
        YgPay3Api api = new YgPay3Api(weixinAccount);
        InputStream inputStream = fileService.downloadIOFromOss("cert/apiclient_cert.p12");
        RedpacketRecord queryRedpack = null;
        queryRedpack = api.queryRedpack(outTradeNo, inputStream);
        return queryRedpack;
    }

}
